package com.anxin.act.busFlow.service;

import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.anxin.act.busFlow.dao.ConfigNodeKeywordDao;
import com.anxin.act.busFlow.dao.WfBusNodeDao;
import com.anxin.act.busFlow.dto.WfConfigNodeDto;
import com.anxin.act.busFlow.entity.ConfigNodeKeyword;
import com.anxin.act.busFlow.entity.WfBusNode;
import com.anxin.common.utils.IdUtils;
import com.anxin.common.utils.StringUtils;
import com.anxin.common.utils.sys.DeptUtils;
import com.anxin.common.utils.sys.RoleUtils;
import com.anxin.common.utils.sys.UserUtils;
import com.anxin.framework.web.service.BaseService;
import com.anxin.common.utils.SecurityUtils;
import com.anxin.sys.filefolder.service.FileFolderService;
import com.anxin.sys.system.entity.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.anxin.act.busFlow.dao.WfConfigNodeDao;
import com.anxin.act.busFlow.entity.WfConfigNode;
import org.springframework.transaction.annotation.Transactional;

/**
 * 业务流程节点Service业务层处理
 *
 * @author jbs
 * @date 2020-04-08
 */
@Service
public class WfConfigNodeService extends BaseService<WfConfigNodeDao,WfConfigNode>{
    @Autowired
    private WfConfigNodeDao wfConfigNodeDao;
    @Autowired
    private FileFolderService fileFolderService;
    @Autowired
    private ConfigNodeKeywordService configNodeKeywordService;
    @Autowired
    private ConfigNodeKeywordDao configNodeKeywordDao;

    /**
     * 查询业务流程节点
     *
     * @param id 业务流程节点ID
     * @return 业务流程节点
     */
    public WfConfigNode getById(String id){
        WfConfigNode  wfConfigNode = wfConfigNodeDao.getById(id);
        // 如果无父节点获取关键字
        if (wfConfigNode.getParentId().equals("0")){
            ConfigNodeKeyword configNodeKeyword = new ConfigNodeKeyword();
            configNodeKeyword.setConfigNodeId(id);
            wfConfigNode.setConfigNodeKeywordList(configNodeKeywordService.findList(configNodeKeyword));
        }
        return wfConfigNode;
    }

    /**
     * 查询业务流程节点列表
     *
     * @param wfConfigNode 业务流程节点
     * @return 业务流程节点
     */
    public List<WfConfigNode> findList(WfConfigNode wfConfigNode){
        // 全部节点
        List<WfConfigNode> allNodeList = wfConfigNodeDao.findList(wfConfigNode);
        this.initName(allNodeList);

        // 查询所有一级节点
        wfConfigNode.setParentId("0");
        List<WfConfigNode> parentNodeList = wfConfigNodeDao.findList(wfConfigNode);
        this.initName(parentNodeList);
        for (WfConfigNode parentNode : parentNodeList) {
            // 一级节点中添加对应的子节点
            parentNode.addChildren(allNodeList);
        }
        return parentNodeList;
    }

    /**
     * 根据folwId和节点类型查询节点
     * @param flowId 流程ID
     * @param nodeType 节点类型
     * @return
     */
    public List<WfConfigNode> findByFlowId(String flowId,String nodeType){
        WfConfigNode wfConfigNode = new WfConfigNode();
        wfConfigNode.setFlowId(flowId);
        wfConfigNode.setNodeType(nodeType);
        return this.findList(wfConfigNode);

    }

    /**
     * 添加各种角色及部门名称
     */
    public void initName(List<WfConfigNode> nodeList){
        for (WfConfigNode wfConfigNode : nodeList) {
            // 可以查看流程的角色
            wfConfigNode.setViewRoleName(RoleUtils.idArrayToName(wfConfigNode.getViewRole()));
            // 可以启动流程的角色
            wfConfigNode.setStartRoleName(RoleUtils.idArrayToName(wfConfigNode.getStartRole()));
            // 可以豁免流程的角色
            wfConfigNode.setImmunityRoleName(RoleUtils.idArrayToName(wfConfigNode.getImmunityRole()));
            // 可以启动流程的部门
            wfConfigNode.setStartDeptName(DeptUtils.idArrayToName(wfConfigNode.getStartDept()));
            // 依赖节点
            wfConfigNode.setRelyNodeName(this.idArrayToName(wfConfigNode.getRelyNode()));
            // 校验附件
            wfConfigNode.setCheckFileName(fileFolderService.idArrayToName(wfConfigNode.getCheckFile()));
            // 选填附件
            wfConfigNode.setOptionalFileName(fileFolderService.idArrayToName(wfConfigNode.getOptionalFile()));

        }
    }

    /**
     * 将节点ID转成节点名称
     * @param relyNode
     * @return
     */
    public String idArrayToName(JSONArray relyNode){
        StringBuffer relyNodeName = new StringBuffer();
        if (relyNode != null){
            for (int i = 0; i < relyNode.size(); i++) {
                WfConfigNode wfConfigNode = this.getById(relyNode.getString(i));
                if (wfConfigNode != null && StringUtils.isNotBlank(wfConfigNode.getNodeName())){
                    if (StringUtils.isNotBlank(relyNodeName)){
                        relyNodeName.append(","+wfConfigNode.getNodeName());
                    }else{
                        relyNodeName.append(wfConfigNode.getNodeName());
                    }
                }
            }
        }
        return relyNodeName.toString();
    }

    /**
     * 保存业务流程节点
     * @param wfConfigNode 流程节点数据
     * @return
     */
    public int save(WfConfigNode wfConfigNode){
        if (StringUtils.isBlank(wfConfigNode.getParentId())){
            wfConfigNode.setParentId("0");
        }
        // 更新业务节点历史数据
        this.updateWfBusNode(wfConfigNode);
        int count = super.save(wfConfigNode);
        // 保存关键字列表
        if (count > 0){
            List<ConfigNodeKeyword> configNodeKeywordList = wfConfigNode.getConfigNodeKeywordList();
            configNodeKeywordDao.deleteByConfigNodeId(wfConfigNode.getId());
            if (configNodeKeywordList != null){
                for (ConfigNodeKeyword configNodeKeyword: configNodeKeywordList) {
                    configNodeKeyword.setConfigNodeId(wfConfigNode.getId());
                    configNodeKeyword.setId(null);
                    configNodeKeyword.setIsNewRecord(false);
                    configNodeKeywordService.save(configNodeKeyword);
                }
            }
        }
        return count;
    }


    /**
     * 更新业务节点历史数据
     * @param wfConfigNode 流程节点数据
     */
    public void updateWfBusNode(WfConfigNode wfConfigNode){
        WfBusNode wfBusNode = new WfBusNode();
        wfBusNode.setNodeId(wfConfigNode.getId());
        wfBusNode.setProcessKey(wfConfigNode.getProcessKey());
        wfBusNode.setFormType(wfConfigNode.getFormType());
        wfBusNode.setFormId(wfConfigNode.getFormId());
        // 更新业务类型 表单类型 表单id
        wfConfigNodeDao.updateFormType(wfBusNode);
        // 更新业务节点对应流程
        wfConfigNodeDao.updateProcessKey(wfBusNode);
    }
    /**
     * 保存业务流程节点
     *
     * @param wfConfigNode 业务流程节点
     * @return 结果
     */
    public int update(WfConfigNode wfConfigNode){
        return super.save(wfConfigNode);
    }


    /**
     * 删除业务流程节点信息
     *
     * @param id 业务流程节点ID
     * @return 结果
     */
    public int deleteById(String id){
        SysUser user = SecurityUtils.getUser();
        return wfConfigNodeDao.deleteById(id,user.getId());
    }

    /**
     * 保存复制的节点信息
     * @param
     * @return
     */
    @Transactional
    public int saveCopyNode(WfConfigNodeDto wfConfigNodeDto) {
        List<String> nodeIds = wfConfigNodeDto.getNodeIds();
        String nodeType = wfConfigNodeDto.getNodeType();
        String flowId = wfConfigNodeDto.getFlowId();
        // 根据节点ID列表查询节点信息
        List<WfConfigNode> wfConfigNodeList = wfConfigNodeDao.findListByNodeIds(nodeIds);
        List<WfConfigNode> newNodesList = new ArrayList<>();
        Map<String,String> newAndOldNodeIdMap = new HashMap<>();
        // 将数据转为树结构
        List<WfConfigNode> treeNodes = wfConfigNodeList.stream().filter(node -> "0".equals(node.getParentId())).map((parentNode) -> {
            String oldParentId = parentNode.getId();
            String newParentId = IdUtils.simpleUUID();
            // 设置信息
            SysUser user = UserUtils.getUser();
            Date date = new Date();
            parentNode.setId(newParentId);
            parentNode.setNodeType(nodeType);
            parentNode.setFlowId(flowId);
            parentNode.setCreateBy(user);
            parentNode.setUpdateBy(user);
            parentNode.setCreateTime(date);
            parentNode.setUpdateTime(date);
            parentNode.setDelFlag("0");
            newAndOldNodeIdMap.put(oldParentId,newParentId);
            newNodesList.add(parentNode);
            parentNode.setChildren(this.getChilNodes(wfConfigNodeList, oldParentId, newParentId, newNodesList, flowId, nodeType, newAndOldNodeIdMap));
            return parentNode;
        }).collect(Collectors.toList());
        // 将树节点复制到新的数据中
        this.setRelyNode(newNodesList, newAndOldNodeIdMap);
        return this.saveBatchNodes(newNodesList);
    }

    private void setRelyNode(List<WfConfigNode> newNodesList, Map<String, String> newAndOldNodeIdMap) {
        newNodesList.forEach(node -> {
            JSONArray relyNodes = node.getRelyNode();
            JSONArray relyIds = new JSONArray();
            if (relyNodes != null) {
                for (Object relyNode : relyNodes) {
                    String relyId = String.valueOf(relyNode);
                    String newNodeId = newAndOldNodeIdMap.get(relyId);
                    if (newNodeId != null) {
                        relyIds.add(newNodeId);
                    }
                }
                if (relyIds == null || relyIds.size() == 0) {
                    node.setRelyNode(null);
                }else{
                    node.setRelyNode(relyIds);
                }
            }
        });
    }

    @Transactional
    public int saveBatchNodes(List<WfConfigNode> newNodesList) {
        return wfConfigNodeDao.saveBatchNodes(newNodesList);
    }

    /**
     * 获取所有子节点
     * @param
     * @param wfConfigNodeList
     * @return
     */
    private List<WfConfigNode> getChilNodes(List<WfConfigNode> wfConfigNodeList, String oldParentId,String newParentId, List<WfConfigNode> newNodesList,String flowId, String nodeType, Map<String,String> newAndOldNodeIdMap) {
        return wfConfigNodeList.stream().filter(node -> StringUtils.equals(node.getParentId(),oldParentId))
                .map((parent) -> {
                    String parentId = IdUtils.simpleUUID();
                    String oldPid = parent.getId();
                    // 设置信息
                    SysUser user = UserUtils.getUser();
                    Date date = new Date();
                    parent.setId(parentId);
                    parent.setParentId(newParentId);
                    parent.setFlowId(flowId);
                    parent.setNodeType(nodeType);
                    parent.setCreateBy(user);
                    parent.setUpdateBy(user);
                    parent.setCreateTime(date);
                    parent.setUpdateTime(date);
                    parent.setDelFlag("0");
                    newAndOldNodeIdMap.put(oldPid,parentId);
                    newNodesList.add(parent);
                    this.getChilNodes(wfConfigNodeList,oldPid,parentId,newNodesList, flowId, nodeType, newAndOldNodeIdMap);
                    return parent;
                }).collect(Collectors.toList());
    }
}
